package com.sky.service.impl;

import com.alibaba.fastjson2.JSON;
import com.sky.api.product.ProductFeignService;
import com.sky.config.CartInterceptor;
import com.sky.constant.CartConstant;
import com.sky.service.CartService;
import com.sky.to.LoginMemberTo;
import com.sky.to.PmsSkuInfoTo;
import com.sky.utils.R;
import com.sky.utils.StringUtils;
import com.sky.vo.CartItemVo;
import com.sky.vo.CartVo;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {

    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private ProductFeignService productFeignService;
    @Resource
    private ThreadPoolExecutor threadPoolExecutor;

    @Override
    public CartItemVo addToCart(Long skuId, Integer num) throws Exception{
        BoundHashOperations ops = getUserOps();
        Object object = ops.get(skuId.toString());
        CartItemVo cartItemVo;
        if (object != null){
            String cartItemStr = object.toString() ;
            //购物车存在该商品
            cartItemVo = JSON.parseObject(cartItemStr, CartItemVo.class);
            cartItemVo.setCount(cartItemVo.getCount() + num);
        } else {
            cartItemVo = new CartItemVo();
            CompletableFuture<Void> getSkuInfo = CompletableFuture.runAsync(() -> {
                // 购物车不存在该商品,调用远程服务查询商品详情
                R<PmsSkuInfoTo> skuInfoById = productFeignService.getSkuInfoById(skuId);
                PmsSkuInfoTo skuInfoByIdData = skuInfoById.getData();
                cartItemVo.setSkuId(skuId);
                cartItemVo.setCount(num);
                cartItemVo.setTitle(skuInfoByIdData.getSkuTitle());
                cartItemVo.setPrice(skuInfoByIdData.getPrice());
                cartItemVo.setSkuName(skuInfoByIdData.getSkuName());
                cartItemVo.setImage(skuInfoByIdData.getSkuDefaultImg());
                cartItemVo.setTotalPrice(cartItemVo.getPrice().multiply(new BigDecimal(cartItemVo.getCount())));
            }, threadPoolExecutor);

            CompletableFuture<Void> getSkuAttrs = CompletableFuture.runAsync(() -> {
                // 远程查询商品属性
                R<List<String>> skuSaleAttrValuesStr = productFeignService.getSkuSaleAttrValueBySkuId(skuId);
                List<String> list = skuSaleAttrValuesStr.getData();
                cartItemVo.setSkuAttr(list);
            }, threadPoolExecutor);

            // 线程阻塞
            CompletableFuture.allOf(getSkuInfo, getSkuAttrs).get();
        }

        // 加入到redis缓存
        ops.put(skuId.toString(), JSON.toJSONString(cartItemVo));
        return cartItemVo;
    }

    @Override
    public CartItemVo getCartItem(Long skuId) {
        BoundHashOperations ops = getUserOps();
        return JSON.parseObject((String) ops.get(skuId.toString()), CartItemVo.class);
    }

    @Override
    public CartVo getUserCartList() {
        LoginMemberTo loginMemberTo = CartInterceptor.threadLocal.get();
        // 查询临时购物车中的数据
        List<CartItemVo> cartList = getUserCartByUserKey(loginMemberTo.getUserKey());
        if (StringUtils.isNotEmpty(loginMemberTo.getUserId())){
            // 已登录(查询用户登录购物车中的数据)
            List<CartItemVo> voList = getUserCartByUserKey(loginMemberTo.getUserId().toString());
            // 把临时购物车的数据添加到登录用户的数据中
            if (StringUtils.isNotEmpty(cartList)){
                for (CartItemVo cartItemVo : cartList) {
                    BoundHashOperations ops = redisTemplate.boundHashOps(CartConstant.REDIS_CART_USER_KEY + loginMemberTo.getUserId().toString());
                    ops.put(cartItemVo.getSkuId(), JSON.toJSONString(cartItemVo));
                }
            }
            // 删除临时购物车中的所有数据
            redisTemplate.delete(CartConstant.REDIS_CART_USER_KEY + loginMemberTo.getUserKey());
            // 合并后的购物车数据
            cartList.addAll(voList);
        }

        CartVo cartVo = new CartVo();
        cartVo.setCarItemVoList(cartList);

        cartVo.setTotalAmount(cartVo.getTotalAmount());

        return cartVo;
    }

    /**
     * 通过用户键查询用户在redis中的购物车数据
     **/
    private List<CartItemVo> getUserCartByUserKey(String userKey){
        List<CartItemVo> cartList = new ArrayList<>();
        BoundHashOperations ops = redisTemplate.boundHashOps(CartConstant.REDIS_CART_USER_KEY + userKey);
        if (Objects.nonNull(ops)){
            List list = ops.values();
            if (StringUtils.isNotEmpty(list)){
                for (Object key : list) {
                    CartItemVo cartItem = JSON.parseObject(key.toString(), CartItemVo.class);
                    cartList.add(cartItem);
                }
            }
        }
        return cartList;
    }

    /**
     * 操作当前用户的购物车数据（如果用户已经登录，则优先操作登录用户的购物车）
     **/
    private BoundHashOperations getUserOps() {
        LoginMemberTo loginMemberTo = CartInterceptor.threadLocal.get();
        String userKey = "";
        if (StringUtils.isNotEmpty(loginMemberTo.getUserId())){
            userKey = CartConstant.REDIS_CART_USER_KEY + loginMemberTo.getUserId();
        } else {
            userKey = CartConstant.REDIS_CART_USER_KEY + loginMemberTo.getUserKey();
        }
        BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(userKey);
        return boundHashOperations;
    }


    @Override
    public void checkItem(Long skuId, Integer checked) {
        Object object = getUserOps().get(skuId);
        if (StringUtils.isNotEmpty(object)){
            CartItemVo cartItemVo = JSON.parseObject(object.toString(), CartItemVo.class);
            cartItemVo.setChecked(checked == 1 ? true: false);
            getUserOps().put(skuId, JSON.toJSONString(cartItemVo));
        }
    }

    @Override
    public void changeItemCount(Long skuId, Integer count) {
        Object object = getUserOps().get(skuId);
        if (StringUtils.isNotEmpty(object)){
            CartItemVo cartItemVo = JSON.parseObject(object.toString(), CartItemVo.class);
            cartItemVo.setCount(count);
            getUserOps().put(skuId, JSON.toJSONString(cartItemVo));
        }
    }

    @Override
    public void deleteSkuItem(Long skuId) {
        Object object = getUserOps().get(skuId);
        if (StringUtils.isNotEmpty(object)){
            getUserOps().delete(skuId);
        }
    }

    @Override
    public List<String> getCartByUserId(Long userId) {
        List<CartItemVo> cartItemVoList = getUserCartByUserKey(userId.toString());
        if (StringUtils.isNotEmpty(cartItemVoList)){
            Set<Long> set = cartItemVoList.stream().map(CartItemVo::getSkuId).collect(Collectors.toSet());
            // 查询商品的最新价格
            R<Map<Long, BigDecimal>> skuInfoByIds = productFeignService.getSkuPriceByIds(set);
            if (skuInfoByIds.getCode() == 0){
                Map<Long, BigDecimal> data = skuInfoByIds.getData();
                for (CartItemVo cartItemVo : cartItemVoList) {
                    BigDecimal price = data.get(cartItemVo.getSkuId());
                    cartItemVo.setPrice(price);
                    cartItemVo.setImage(cartItemVo.getImage());
                    cartItemVo.setTotalPrice(price.multiply(new BigDecimal(cartItemVo.getCount())));
                }
            }
            return cartItemVoList.stream().map(data -> JSON.toJSONString(data)).collect(Collectors.toList());
        }
        return null;
    }
}


